home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-01-19 | 8.1 KB | 300 lines | [TEXT/MPS ] |
- (*******************************************************************
-
- Window Menu.p
-
- MDEF for dynamic Window menu demo.
-
- (c) 1988, by Clifford Story & Attic Software
-
- *******************************************************************)
-
- unit WDEF;
-
- (******************************************************************)
-
- interface
-
- (******************************************************************)
-
- uses memtypes, quickdraw, osintf, toolintf, Common;
-
- (******************************************************************)
-
- procedure menudef(message : integer; themenu : MenuHandle;
- var menurect : Rect; hitpoint : Point;
- var whichitem : integer);
-
- (******************************************************************)
-
- implementation
-
- (******************************************************************)
-
- type
-
- QDrecord = record
- randSeed : long;
- screenBits : BitMap;
- arrow : Cursor;
- dkGray : Pattern;
- ltGray : Pattern;
- gray : Pattern;
- black : Pattern;
- white : Pattern;
- thePort : GrafPtr;
- end;
- QDpointer = ^QDrecord;
-
- (******************************************************************)
-
- procedure menudraw(themenu : MenuHandle; var menurect : Rect); forward;
- procedure menuchoose(themenu : MenuHandle; var menurect : Rect;
- hitpoint : Point; var whichitem : integer); forward;
- procedure menusize(themenu : MenuHandle); forward;
-
- (******************************************************************)
-
- {$R-}
- {$SC+}
-
- (*******************************************************************
-
- menudef
- -------
-
- An MDEF is called to do three different things: draw the menu,
- hit-test a mouse location, or calculate the menu dimensions.
- The “message” parameter determines which service is requested,
- so the MDEF simply branches on “message” to specialized routines
- that handle the specific functions.
-
- *******************************************************************)
-
- procedure menudef(message : integer; themenu : MenuHandle;
- var menurect : Rect; hitpoint : Point;
- var whichitem : integer);
-
- begin
-
- case message of
- mDrawMsg : menudraw(themenu, menurect);
- mChooseMsg : menuchoose(themenu, menurect,
- hitpoint, whichitem);
- mSizeMsg : menusize(themenu);
- end;
-
- end;
-
- (******************************************************************
-
- QDglobals
- ---------
-
- The QDglobals function returns a pointer to the QuickDraw
- globals. This allows procedure definitions and desk accessories
- to access the QD globals even though they can't call InitGraf.
-
- ******************************************************************)
-
- function QDglobals : QDpointer;
-
- var
- thepointer : longpointer;
-
- begin
-
- thepointer := longpointer(currenta5);
- thepointer := longpointer(thepointer^);
- QDglobals := QDpointer(long(thepointer^)
- - sizeof(QDrecord) + sizeof(GrafPtr));
-
- end;
-
- (*******************************************************************
-
- menudraw
- --------
-
- The “menudraw” routine draws the menu.
-
- The first item is the “Draw Front Window” command, and the
- second is the separating line before the list of window. If
- the first item is disabled, then it should be grayed out, by
- painting over it with gray.
-
- The remaining items are found in the window list that is kept
- by the system. The low-memory global “windowlist” contains a
- pointer to the front window. Each window record includes in
- turn a pointer to the next window in the list; the last window's
- pointer is nil.
-
- Drawing the menu, then, is a simple matter of walking the window
- list and drawing each successive window title. But the menu
- should include only application windows; for one thing, some DA
- windows don't have titles. So the trip through the window list
- will skip over windows that aren't “userKind”.
-
- *******************************************************************)
-
- procedure menudraw(themenu: MenuHandle; var menurect: Rect);
-
- var
- height : integer;
- width : integer;
- therect : Rect;
- thewindow : WindowPeek;
-
- begin
-
- height := menurect.top + 12;
- width := menurect.left + 12;
-
- MoveTo(width, height);
- DrawString('Zoom Front Window');
- MoveTo(menurect.right - CharWidth('W') - 15, height);
- DrawChar(chr(17));
- DrawChar('W');
-
- if not BitTst(@themenu^^.enableFlags, 30) then begin
- PenPat(QDglobals^.gray);
- PenMode(patBic);
- with menurect do
- SetRect(therect, left, top, right, top + 16);
- PaintRect(therect);
- PenNormal;
- end;
-
- height := height + 16;
- MoveTo(menurect.left, menurect.top + 24);
- Line(menurect.right - menurect.left, 0);
-
- thewindow := WindowPeek(longpointer(windowlist)^);
- while thewindow <> nil do
- with thewindow^ do begin
- if visible and (windowkind = userKind) then begin
- height := height + 16;
- MoveTo(width, height);
- DrawString(titlehandle^^);
- end;
- thewindow := nextwindow;
- end;
-
- end;
-
- (*******************************************************************
-
- menuchoose
- ----------
-
- This routine is passed the mouse position, and sets the
- “whichitem” parameter to the corresponding menu item.
-
- Since all the menu items are the same height, it's easy to
- determine which one the mouse is in - provided it's somewhere
- in the menu. If that item is disabled, however, its number
- should not be returned; instead the routine should return zero.
-
- Finally, if the mouse is in an active item, and that item is
- different from the original value of “whichitem”, then the old
- item should be un-highlighted, and the new one highlighted.
-
- *******************************************************************)
-
- procedure menuchoose(themenu : MenuHandle; var menurect : Rect;
- hitpoint : Point; var whichitem : integer);
-
- var
- theitem : integer;
- therect : Rect;
-
- begin
-
- if PtInRect(hitpoint, menurect) then
- theitem := 1 + ((hitpoint.v - menurect.top) div 16)
- else
- theitem := 0;
-
- if not BitTst(@themenu^^.enableFlags, 31 - theitem) then
- theitem := 0;
-
- if theitem <> whichitem then begin
-
- therect := menurect;
- therect.bottom := therect.top + 16 * theitem;
- therect.top := therect.bottom - 16;
- InvertRect(therect);
-
- if whichitem > 0 then begin
- therect.bottom := menurect.top + 16 * whichitem;
- therect.top := therect.bottom - 16;
- InvertRect(therect);
- end;
-
- whichitem := theitem;
-
- end;
-
- end;
-
- (*******************************************************************
-
- menusize
- --------
-
- This routine calculates the dimensions of the menu rectangle.
-
- Similarly to the “menudraw” routine, this routine walks the
- window list, and finds the widest item, to base the menu width
- on. The menu height is simply the sum of the item heights.
- The results are stored in the MenuHandle.
-
- A note: Odd things happened in this routine, with the string
- width changing as windows were opened. I can't figure why this
- occurred, since Inside Mac says the Menu Manager sets the port
- to the Window Manager port. Anyway, the TextFont, TextSize and
- TextFace calls cleared up the problem.
-
- *******************************************************************)
-
- procedure menusize(themenu : MenuHandle);
-
- var
- thewidth : integer;
- theheight : integer;
- thewindow : WindowPeek;
- newwidth : integer;
-
- begin
-
- TextFont(systemFont);
- TextSize(12);
- TextFace([]);
-
- theheight := 32;
- thewidth := StringWidth('Zoom Front Window')
- + CharWidth('W') + 39;
-
- thewindow := WindowPeek(longpointer(windowlist)^);
-
- while thewindow <> nil do
- with thewindow^ do begin
- if visible and (windowkind = userKind) then begin
- theheight := theheight + 16;
- newwidth := StringWidth(titlehandle^^) + 16;
- if newwidth > thewidth then
- thewidth := newwidth;
- end;
- thewindow := nextwindow;
- end;
-
- themenu^^.menuHeight := theheight;
- themenu^^.menuWidth := thewidth;
-
- end;
-
- (******************************************************************)
-
- end.
-
- (******************************************************************)
-